#ifndef _SUBSCRIBER_H_
#define _SUBSCRIBER_H_

#include <string>
#include <list>
#include "Message.h"
#include "staffmqclientexport.h"

namespace smq
{
  typedef std::list<MessageHeader> MessageHeaderList; //!< message headers list
  typedef std::list<std::string> StringList; //!< string list

  class MessageHandler;

  //! Subscriber
  /*! class for subscribing to message queue(s) */
  class STAFFMQ_CLIENT_EXPORT Subscriber
  {
  public:
    Subscriber();
    virtual ~Subscriber();

    //! initialize subscriber
    /*! \param sSubscriberName - subscriber name
        \param sServerHost - server host
        \param ushServerPort - server port
        */
    void Init(const std::string& sSubscriberName, const std::string& sServerHost = "127.0.0.1", unsigned short ushServerPort = 8768);

    //! set message handler
    /*! \param  pMessageHandler - message handler
      */
    void SetHandler(MessageHandler* pMessageHandler);

    //! subscribe to queue
    /*! \param  sQueueName - queue name
        */
    void Subscribe(const std::string& sQueueName);

    //! unsubscribe queue
    /*! \param  sQueueName - queue name
        */
    void Unsubscribe(const std::string& sQueueName);

    //! start Subscriber(switch to infinite message handling loop)
    /*! \param  bThread - start subscriber as separate thread
    */
    void Start(bool bThread = false);

    //! stop Subscriber
    void Stop();
    
    //! is subscriber currently stopping
    /*! \return true, if Stop() function was called
      */
    bool IsStopping();
    
    //! is subscriber working (if started as separate thread)
    /*! \return true, if subscriber working
      */
    bool IsWorking() const;
    
    //! wait for subscriber ends (if started as separate thread)
    void Wait();

    //! get server queues list
    /*! \param rlsQueues - (out) queue list
      */
    void GetQueueList(StringList& rlsQueues);

    //! get server queues list with filter
    /*! \param  sFilter - filter
        \param rlsQueues - (out) queue list
      */
    void GetFilteredQueueList(const std::string& sFilter, StringList& rlsQueues);

    //! get queue length
    /*! \param  sQueueName - queue name
        \return queue length
      */
    int GetQueueLength(const std::string& sQueueName);

    //! get last message from server's queue
    /*! \param  sQueueName - queue name
        \param  rMsg - (out) last message in server queue
    */
    void GetLastMessage(const std::string& sQueueName, Message& rMsg);

    //! get message headers list
    /*! \param  sQueueName - queue name
        \param  rlsMessages - (out) list of message headers, currently in server queue
    */
    void GetMessageHeadersList(const std::string& sQueueName, MessageHeaderList& rlsMessages);

    //! get last message from server's queue
    /*! \param  sQueueName - queue name
        \param  sId - message id
        \param  rMsg - (out) last message in server queue
    */
    void GetMessage(const std::string& sQueueName, const std::string& sId, Message& rMsg);

    //! receive next message from subscribed queues
    /*! \param  rMsg - received message
        \param  bRemove - remove received message from queue
      */
    void ReceiveMessage(Message& rMsg, bool bRemove = false);

    //! remove message from queue
    /*! \param  sQueueName - queue name
        \param  sMsgId - message id
      */
    void RemoveMessage(const std::string& sQueueName, const std::string& sMsgId);

#ifndef STAFFMQ_NO_DEPRECATED
    //! deprecated function
    void Subscribe(const std::string& sQueueName, MessageHandler* pMessageHandler);
#endif //  STAFFMQ_NO_DEPRECATED

  private:
    struct SubscriberImpl;
    SubscriberImpl* m_pImpl;
  };


  //! message handler
  class STAFFMQ_CLIENT_EXPORT MessageHandler
  {
  public:
    virtual ~MessageHandler() {}

    //! operator(), called when new message arrives
    /*! \param rSubscriber - message Subscriber, bound with handler
        \param rMsg - arrived message
        */
    virtual void operator()(Subscriber& rSubscriber, const Message& rMsg) = 0;
  };

}

#endif // _SUBSCRIBER_H_
